%matplotlib inline
import numpy as np
import pandas as pd
import os
from scipy import stats
import matplotlib.pyplot as plt
import statsmodels.api as sm
from statsmodels.graphics.api import qqplot
import plotly
plotly.offline.init_notebook_mode()
import plotly.offline as po
import plotly.plotly as py
import plotly.graph_objs as go
import cufflinks as cf
import plotly.figure_factory as ff
excel = pd.ExcelFile('./dados/IndicesDeCredito.xlsx')
dados = pd.DataFrame()
print('Dados sobre:')
for tab in excel.sheet_names:
print(tab)
df = excel.parse(tab, index_col = 0, skiprows = 1)
if df.shape[1] > 1:
df.columns = excel.parse(tab, skiprows = 0, index_col = 0).columns
else:
df.columns = [tab]
df.index.name = 'Dates'
dados = pd.concat([dados, df],join='outer',axis=1)
dados.dropna().tail()
Mediremos o excesso de retorno ajustado por Duration e ver se há prêmio de risco
$R_{t+1}^{BRSvg-XS}=R_{t+1}^{BRSvg} - \frac{D_t^{BRSvg}}{D_t^{UST}} R_{t+1}^{UST}$
$R_{t+1}^{EUR-XS}=R_{t+1}^{EUR} - \frac{D_t^{EUR}}{D_t^{BRSvg}} R_{t+1}^{BRSvg}$
debts = pd.DataFrame()
debts = dados.loc[:, ~dados.iloc[:, :6].columns.str.contains('Duration')].resample('M').last().pct_change(1)
debts = pd.concat([debts, dados.loc[:, dados.iloc[:, :6].columns.str.contains('Duration')].resample('M').last().shift(1)],
axis = 1, join = 'inner')
debts.dropna(inplace=True)
print('Periodo de analise:')
print(min(debts.index))
print(max(debts.index))
print(str(debts.shape[0] - 1) + ' months')
risk_premia = pd.DataFrame()
risk_premia['BRSvg_xs'] = debts['BRSvg'] - (debts['BRSvg_Duration'] / debts['UST_Duration']) * debts['UST']
risk_premia['EUR_xs'] = debts['Eurobonds'] - (debts['Eurobonds_Duration'] / debts['BRSvg_Duration']) * debts['BRSvg']
for col in risk_premia.columns:
risk_premia[col + '_cum'] = (1 + risk_premia[col]).cumprod() - 1
cf.go_offline()
cf.set_config_file(offline=True, world_readable=False, theme='ggplot')
#fig = risk_premia.iplot(secondary_y = [col for col in risk_premia.columns if '_cum' in col])
fig1 = risk_premia.iplot(columns = [col for col in risk_premia.columns if '_cum' not in col],
kind = 'bar',
asFigure=True)
fig2 = risk_premia.iplot(columns = [col for col in risk_premia.columns if '_cum' in col],
secondary_y = [col for col in risk_premia.columns if '_cum' in col],
asFigure=True)
fig2['data'].extend(fig1['data'])
fig2['layout']['title'] = 'Premio de risco de credito de BRSvg e Eurobonds'
fig2['layout']['yaxis1']['title'] = 'Premio de risco mensal (barras)'
fig2['layout']['yaxis2']['title'] = 'Premio de risco acumulado (linhas)'
po.iplot(fig2)
risk_premia['BRSvg_xs_simple'] = debts['BRSvg'] - debts['UST']
risk_premia['EUR_xs_simple'] = debts['Eurobonds'] - debts['BRSvg']
data_matrix = [[''] + [i for i in risk_premia.columns if '_cum' not in i],
['Mean'] + [str(round((((1 + risk_premia[i].mean()) ** (12)) - 1)*100, 2)) + '%'
for i in risk_premia.columns if '_cum' not in i],
['Vol.'] + [str(round(((np.log(1+risk_premia[i]).std()) * np.sqrt(12))*100, 2)) + '%'
for i in risk_premia.columns if '_cum' not in i],
['Sharpe'] + [round(((((1 + risk_premia[i].mean()) ** (12)) - 1) / (risk_premia[i].std() * np.sqrt(12))), 2)
for i in risk_premia.columns if '_cum' not in i]]
table = ff.create_table(data_matrix)
po.iplot(table)
Comparando os retornos anualizados e os respectivos Sharpe Ratios, notamos que existe premio de risco para divida soberana brasileira (BRSvg), medido pelo excesso de retorno de BRSvg em relação a UST. No entanto, nota-se que a Duration de ambos, na média, é muito parecida, pois o excesso de retorno simples e ajustado por duration são muito próximos. Na realiade, o Sharpe Ratio do exesso simples é ligeiramente maior.
Já para Eurobonds, notamos que o premio de risco vs. BRSvg não existe.
Estimaremos o excesso de retorno das Debentures ligadas ao IPCA e ao CDI.
Para isso, primeiramente rodaremos uma regressão para estimarmos os $\beta$'s como proxy de Duration
estimar: $R_{t+1}^{DebIPCA} = \alpha + \beta^{DebIPCA}{\Delta}y_{t+1}^{real} + \epsilon_t$
estimar: $R_{t+1}^{Gov} = \alpha + \beta^{Gov}{\Delta}y_{t+1}^{real} + \epsilon_t$
calcular: $R_{t+1}^{DebIPCA-XS}=R_{t+1}^{DebIPCA} - \frac{\beta^{DebIPCA}}{\beta^{Gov}} R_{t+1}^{Gov}$
debentures = pd.DataFrame()
indices = pd.DataFrame()
for col in dados.iloc[:, 6:].columns:
if 'Yield' not in col:
indices[col] = dados[col]
yields = pd.DataFrame()
for col in dados.iloc[:, 6:].columns:
if 'Yield' in col:
yields[col] = dados[col]
indices = indices.resample('BM').last()
indices = indices.pct_change(1)
yields = yields.resample('BM').last()
yields = yields - yields.shift(1)
debentures = pd.concat([indices, yields], axis = 1, join = 'outer').ffill().dropna()
# regressao para achar beta DebIPCA
reg = sm.OLS(endog = debentures['DebenturesIPCA'], exog = sm.add_constant(debentures['RealYield5Y']), hasconst = True)
reg_deb_ipca = reg.fit()
print(reg_deb_ipca.summary())
# regressao para achar beta Gov
reg = sm.OLS(endog = debentures['NTNBs'], exog = sm.add_constant(debentures['RealYield5Y']), hasconst = True)
reg_gov = reg.fit()
print(reg_gov.summary())
Ambos $\beta$'s são significantes, então podemos, agora, estimar o excesso de retorno ajustado por duration (ou $\beta$)
print('Beta DebIPCA = %.3f' %reg_deb_ipca.params[1])
print('Beta Gov = %.3f' %reg_gov.params[1])
deb_ipca = pd.DataFrame()
deb_ipca['DebIPCA_xs'] = debentures['DebenturesIPCA'] - (reg_deb_ipca.params[1] / reg_gov.params[1]) * debentures['NTNBs']
deb_ipca['DebIPCA_xs_simple'] = debentures['DebenturesIPCA'] - debentures['NTNBs']
for col in deb_ipca.columns:
deb_ipca[col + '_cum'] = (1 + deb_ipca[col]).cumprod() - 1
cf.go_offline()
cf.set_config_file(offline=True, world_readable=False, theme='ggplot')
fig1 = deb_ipca.iplot(columns = [col for col in deb_ipca.columns if '_cum' not in col],
kind = 'bar',
asFigure=True)
fig2 = deb_ipca.iplot(columns = [col for col in deb_ipca.columns if '_cum' in col],
secondary_y = [col for col in deb_ipca.columns if '_cum' in col],
asFigure=True)
fig2['data'].extend(fig1['data'])
fig2['layout']['title'] = 'Premio de risco ID-IPCA'
fig2['layout']['yaxis1']['title'] = 'Premio de risco mensal (barras)'
fig2['layout']['yaxis2']['title'] = 'Premio de risco acumulado (linhas)'
po.iplot(fig2)
data_matrix = [[''] + [i for i in deb_ipca.columns if '_cum' not in i],
['Mean'] + [str(round((((1 + deb_ipca[i].mean()) ** (12)) - 1)*100, 2)) + '%'
for i in deb_ipca.columns if '_cum' not in i],
['Vol.'] + [str(round(((np.log(1+deb_ipca[i]).std()) * np.sqrt(12))*100, 2)) + '%'
for i in deb_ipca.columns if '_cum' not in i],
['Sharpe'] + [round(((((1 + deb_ipca[i].mean()) ** (12)) - 1) / (deb_ipca[i].std() * np.sqrt(12))), 2)
for i in deb_ipca.columns if '_cum' not in i]]
table = ff.create_table(data_matrix)
po.iplot(table)
Nota-se que há um alto premio de risco, e com alto Sharpe, para o excesso de retorno ajustado por duration.
Devemos tomar cuidado, no entanto, pois a amostra é pequena e foi necessário preencher as lacunas com o método Forward-Fill para ter-se uma série contínua.
calcular e ver significancia do $\beta$: $R_{t+1}^{DebCDI} - R_{t+1}^{CDI} = \alpha + \beta^{DebCDI}{\Delta}y_{t+1}^{nom}$
# regressao para achar beta DebCDI
reg = sm.OLS(endog = debentures['DebenturesCDI'] - debentures['CDI'],
exog = sm.add_constant(debentures['NominalYield5Y']),
hasconst = True)
reg_deb_cdi = reg.fit()
print(reg_deb_cdi.summary())
O coeficiente nao é significante. Não podemos, então, concluir se há premio de risco para o caso de ID-CDI.